home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Testing & Debugging / General tools / Audit app & dcmd / Src / AuditDCMD.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-17  |  11.0 KB  |  473 lines  |  [TEXT/MPS ]

  1. /*
  2.  * AuditDCMD.c
  3.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  4.  * Programmed by Martin Minow,
  5.  *    Internet:    minow@apple.com
  6.  *    AppleLink:    MINOW
  7.  * Version of January 4, 1993
  8.  *
  9.  * Provide formatted access to a Audit from within MacsBug.
  10.  *
  11.  * The following commands are supported:
  12.  *
  13.  *    Audit NAME on            Turn logging on for this log
  14.  *    Audit NAME off            Turn logging off
  15.  *    Audit NAME write            Display the entire log (including
  16.  *                                free areas that contain "real" data).
  17.  * Note that the log area must already have been created.
  18.  *
  19.  * AuditDCMD is built by the following commands (they are best
  20.  * placed in a suitable Makefile). BuildDCMD and the libraries
  21.  * are distributed with MacsBug. This sequence assumes MPW 3.2
  22.  * + cut here
  23.         C                                    ∂
  24.             -i {DCMDIncludes}                ∂
  25.             -o AuditDCMD.c.o                ∂
  26.             AuditDCMD.c
  27.         C                                    ∂
  28.             -i {DCMDIncludes}                ∂
  29.             -o AuditEntryFormat.c.o            ∂
  30.             AuditEntryFormat.c
  31.         Link                                ∂
  32.             -o Audit                        ∂
  33.             {DCMDLibraries}dcmdGlue.a.o        ∂
  34.             AuditDCMD.c.o                    ∂
  35.             AuditEntryFormat.c.o            ∂
  36.             "{Libraries}"Runtime.o            ∂
  37.             "{Libraries}"Interface.o
  38.         {DCMD}BuildDcmd Audit 1000
  39.         Echo 'include "Audit";'                ∂
  40.             | Rez -a -o "{systemFolder}Debugger Prefs"
  41.  * - to here
  42.  *    Note:  Be sure to link dcmdGlue.a.o first.  The files in the
  43.  *    dcmd libraries folder are distributed with Macsbug.
  44.  */
  45. #include <Types.h>
  46. /*
  47.  * AuditDCMD.c
  48.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  49.  * Programmed by Martin Minow,
  50.  *    Internet:    minow@apple.com
  51.  *    AppleLink:    MINOW
  52.  * Version of January 14, 1993
  53.  *
  54.  * Edit History
  55.  *    93.01.09 MM        First public release
  56.  *    93.01.14 MM        Think and MPW generate different record sizes;
  57.  *                    a disaster if you create an Audit Record under
  58.  *                    Think and call Audit compiled under MPW. Also
  59.  *                    added a test for record sizes and included
  60.  *                    record size information in the AuditRecord.
  61.  *
  62.  * This is a MacsBug DCMD that can display AuditRecord contents.
  63.  */
  64. #include <Traps.h>
  65. #include <GestaltEqu.h>
  66. #include <Memory.h>
  67. #include "Audit.h"
  68. /*
  69.  * This file should be copied from the MacsBug distribution. Note
  70.  * that we have our own display routines: only dcmdDrawString,
  71.  * dcmdDrawLine, and dcmdDrawText are used.
  72.  */
  73. #include "dcmd.h"
  74. /*
  75.  * The version id's are defined as (majorVersion << 8) | minorVersion
  76.  */
  77. #define kAuditDCMDEarliestVersion    ((1 << 8) | 2)
  78. #define kAuditDCMDLatestVersion        ((1 << 8) | 2)
  79.  
  80. #ifndef TRUE
  81. #define TRUE    1
  82. #define FALSE    0
  83. #endif
  84. /*
  85.  * These values must match values in Audit.c
  86.  */
  87. #define kAuditMagicHeaderSize    7            /* Size in longwords            */
  88. #define kAuditMagicHeader_0        0x4E560000    /* First word in Gestalt result    */
  89.  
  90. #define LOG        (*auditPtr)
  91. #define ENTRY    (*entryPtr)
  92.  
  93. AuditPtr                DCMDGetAuditPtr(
  94.         OSType                        gestaltSelector
  95.     );
  96. void                    DumpAudit(
  97.         register AuditPtr            auditPtr
  98.     );
  99. void                    DumpAuditEntry(
  100.         register AuditPtr            auditPtr,
  101.         register AuditEntryPtr        entryPtr
  102.     );
  103. Boolean                    CompareString(
  104.         const StringPtr                a,
  105.         const StringPtr                b
  106.     );
  107. void                    PutUnsignedLeadingZeros(
  108.         unsigned long                value,
  109.         short                        digits
  110.     );
  111. void                    PutHexLeadingZeros(
  112.         unsigned long                value,
  113.         short                        digits
  114.     );
  115. void                    PutUnsigned(
  116.         unsigned long                value
  117.     );
  118. void                    PutSigned(
  119.         signed long                    value
  120.     );
  121. void                    PutOSType(
  122.         OSType                        datum
  123.     );
  124. void                    PutChar(
  125.         unsigned char                datum
  126.     );
  127. void                    PutPascalString(
  128.         const StringPtr                datum
  129.     );
  130. pascal void                CommandEntry(
  131.         dcmdBlock            *paramPtr
  132.     );
  133. pascal void                dcmdSwapWorlds(void);
  134. void                    PutLine(void);
  135.  
  136. pascal void
  137. CommandEntry(
  138.         dcmdBlock            *paramPtr
  139.     )
  140. {
  141.         register AuditPtr        auditPtr;
  142.         Str255                    formatString;
  143.         OSType                    gestaltSelector;
  144.         Boolean                    oldEnableState;
  145.         
  146.         switch (paramPtr->request) {
  147.         case dcmdDoIt:        
  148.             dcmdSwapWorlds();                /* TMON needs this        */
  149.             (void) dcmdGetNextParameter(formatString);
  150.             while (formatString[0] < 4)
  151.                 formatString[++formatString[0]] = ' ';
  152.             if (formatString[0] == (4 + 2)
  153.                 && formatString[1] == '\''
  154.                 && formatString[5] == '\'')
  155.                 BlockMove(&formatString[2], &gestaltSelector, 4);
  156.             else {
  157.                 BlockMove(&formatString[1], &gestaltSelector, 4);
  158.             }
  159.             PutPascalString("\pAudit ");
  160.             PutOSType(gestaltSelector);
  161.             PutLine();
  162.             auditPtr = DCMDGetAuditPtr(gestaltSelector);
  163.             if (auditPtr == NULL) {
  164.                 dcmdDrawLine("\pUndefined audit area");
  165.                 goto drawHelp;
  166.             }
  167.             else {
  168.                 PutPascalString("\pAudit area at ");
  169.                 PutHexLeadingZeros((unsigned long) auditPtr, 8);
  170.                 PutLine();
  171.                 oldEnableState = (LOG.flags & kAuditEnabledMask) != 0;
  172.                 (void) dcmdGetNextParameter(formatString);
  173.                 if (CompareString("\pON", formatString)) {
  174.                     LOG.flags |= kAuditEnabledMask;
  175.                     PutPascalString("\pAuditing enabled, was ");
  176.                     goto turnOffExit;
  177.                 }
  178.                 else if (CompareString("\pOFF", formatString)) {
  179.                     LOG.flags &= ~kAuditEnabledMask;
  180.                     PutPascalString("\pAuditing disabled, was ");
  181. turnOffExit:        PutPascalString((oldEnableState)
  182.                         ? "\penabled" : "\pdisabled");
  183.                     PutLine();
  184.                 }
  185.                 else if (CompareString("\pWRITE", formatString)
  186.                       || formatString[0] == 0)
  187.                     DumpAudit(auditPtr);
  188.                 else {
  189.                     dcmdDrawLine("\pUnknown Audit command.");
  190.                     goto drawHelp;
  191.                 }
  192.             }
  193.             dcmdSwapWorlds();                /* TMON needs this        */
  194.             break;
  195.         case dcmdHelp:
  196.             dcmdDrawLine("\pAudit formats Audit record area.");
  197. drawHelp:    dcmdDrawLine("\pFormat: Audit NAME on | Audit NAME off"
  198.                 " | Audit NAME write");
  199.             dcmdDrawLine("\pWhere NAME is the Audit Gestalt identifier.");
  200.             dcmdDrawLine("\p\"Write\" is assumed if no command is given.");
  201.             break;
  202.         }
  203. }
  204.  
  205. AuditPtr
  206. DCMDGetAuditPtr(
  207.         OSType            gestaltSelector
  208.     )
  209. {
  210.         auto long                    gestaltResponse;
  211.         register AuditPtr            auditPtr;
  212.  
  213.         auditPtr = NULL;
  214.         if (Gestalt(gestaltSelector, &gestaltResponse) != noErr)
  215.             dcmdDrawLine("\pNo such AuditRecord");
  216.         else if (gestaltResponse == 0
  217.               || (gestaltResponse & 0x3) != 0)
  218.              dcmdDrawLine("\pThis is not an AuditRecord (wrong Gestalt value)");
  219.         else {
  220.             auditPtr = (AuditPtr) gestaltResponse;
  221.             if (((unsigned long *) auditPtr)[-kAuditMagicHeaderSize]
  222.                     != kAuditMagicHeader_0) {
  223.                 dcmdDrawLine("\pThis is not an AuditRecord (wrong header)");
  224.                 auditPtr = NULL;
  225.             }
  226.             else if (LOG.version.u.low < kAuditDCMDEarliestVersion) {
  227.                 dcmdDrawLine("\pThis AuditRecord release is earlier than our minimum");
  228.                 auditPtr = NULL;
  229.             }
  230.             else if (LOG.version.u.high > kAuditDCMDLatestVersion) {
  231.                 dcmdDrawLine("\pThis AuditRecord release is later than our maximum");
  232.                 auditPtr = NULL;
  233.             }
  234.             else if (LOG.recordSize != kAuditRecordSize) {
  235.                 dcmdDrawLine("\pRecord size mismatch");
  236.                 PutPascalString("\pRecord size mismatch, expecting ");
  237.                 PutHexLeadingZeros(kAuditRecordSize, 8);
  238.                 PutPascalString(", got ");
  239.                 PutHexLeadingZeros(LOG.recordSize, 8);
  240.                 PutLine();
  241.                 auditPtr = NULL;
  242.             }
  243.  
  244.             
  245.         }
  246.         return (auditPtr);
  247. }
  248.  
  249. void
  250. DumpAudit(
  251.         register AuditPtr        auditPtr
  252.     )
  253. {
  254.         register AuditQueueEntryPtr        queueEntryPtr;
  255.  
  256.         PutPascalString("\pAuditRecord version: ");
  257.         PutHexLeadingZeros((unsigned long) LOG.version.u.low, 4);
  258.         PutPascalString("\p low, ");
  259.         PutHexLeadingZeros((unsigned long) LOG.version.u.high, 4);
  260.         PutPascalString("\p high.");
  261.         PutLine();
  262.         PutPascalString("\pDebugging is ");
  263.         PutPascalString(((LOG.flags & kAuditEnabledMask)
  264.             ? "\penabled" : "\pdisabled"));
  265.         if (LOG.lostData == 0)
  266.             PutPascalString("\p, no pending lost data");
  267.         else {
  268.             PutUnsigned(LOG.lostData);
  269.             PutPascalString("\p pending lost data");
  270.         }
  271.         PutPascalString("\p, User refNum: ");
  272.         PutHexLeadingZeros((unsigned long) LOG.refNum, 8);
  273.         PutLine();
  274.         PutPascalString("\plogicalRAMSize: ");
  275.         PutHexLeadingZeros((unsigned long) LOG.logicalRAMSize, 8);
  276.         PutLine();
  277.         /*
  278.          * First dump all entries in the free queue.
  279.          */
  280.         PutPascalString("\pAudit area (already displayed)");
  281.         PutLine();
  282.         queueEntryPtr = (AuditQueueEntryPtr) LOG.free.queue.qHead;
  283.         if (queueEntryPtr != NULL) {
  284.             for (;;) {
  285.                 DumpAuditEntry(auditPtr, &queueEntryPtr->theEntry);
  286.                 if (queueEntryPtr == (AuditQueueEntryPtr) LOG.free.queue.qTail)
  287.                     break;
  288.                 queueEntryPtr = (AuditQueueEntryPtr) queueEntryPtr->qLink;
  289.             }
  290.         }
  291.         /*
  292.          * Then dump all entries in the data queue.
  293.          */
  294.         PutPascalString("\pAudit area (to be displayed)");
  295.         PutLine();
  296.         queueEntryPtr = (AuditQueueEntryPtr) LOG.data.queue.qHead;
  297.         if (queueEntryPtr != NULL) {
  298.             for (;;) {
  299.                 DumpAuditEntry(auditPtr, &queueEntryPtr->theEntry);
  300.                 if (queueEntryPtr == (AuditQueueEntryPtr) LOG.data.queue.qTail)
  301.                     break;
  302.                 queueEntryPtr = (AuditQueueEntryPtr) queueEntryPtr->qLink;
  303.             }
  304.         }
  305.         PutPascalString("\pEnd of Audit display");
  306.         PutLine();
  307. }
  308.  
  309. void
  310. DumpAuditEntry(
  311.         register AuditPtr            auditPtr,
  312.         register AuditEntryPtr        entryPtr
  313.     )
  314. {
  315.         Str255                        result;
  316.         
  317. #define DATA    (ENTRY.data)
  318.         if (ENTRY.tickCount != 0) {
  319.             FormatAuditEntryTimestamp(auditPtr, entryPtr, result);
  320.             PutPascalString(result);
  321.             PutPascalString("\p: ");
  322.             FormatAuditEntryData(entryPtr, result);
  323.             PutPascalString(result);
  324.             PutLine();
  325.         }
  326. #undef DATA
  327. }
  328.             
  329. /*
  330.  * Compare two strings. a is the keyword we're looking
  331.  * for: it is always specified in upper-case. b is
  332.  * the test string. It is case-converted. Note that
  333.  * this code presumes that the test words are in
  334.  * 7-bit ASCII.
  335.  */
  336. Boolean
  337. CompareString(
  338.         const StringPtr            a,
  339.         const StringPtr            b
  340.     )
  341. {
  342.         register short            i;
  343.         register unsigned char    c;
  344.         
  345.         if (a[0] != b[0])
  346.             return (FALSE);
  347.         else {
  348.             for (i = 1; i <= a[0]; i++) {
  349.                 c = b[i];
  350.                 if (c >= 'a' && c <= 'z')
  351.                     c -= ('a' - 'A');
  352.                 if (c != a[i])
  353.                     return (FALSE);
  354.             }
  355.             return (TRUE);
  356.         }
  357. }
  358.  
  359. /*
  360.  * Output an n-digit value with leading zeros.
  361.  */
  362. void
  363. PutUnsignedLeadingZeros(
  364.         unsigned long        value,
  365.         short                digits
  366.     )
  367. {
  368.         if (--digits > 0)
  369.             PutUnsignedLeadingZeros(value / 10, digits);
  370.         PutChar((value % 10) + '0');
  371. }
  372.  
  373. /*
  374.  * Output a signed decimal longword.
  375.  */
  376. void
  377. PutSigned(
  378.         signed long            value
  379.     )
  380. {
  381.         if (value < 0) {
  382.             PutChar('-');
  383.             value = (-value);
  384.         }
  385.         PutUnsigned((unsigned long) value);
  386. }
  387.  
  388. /*
  389.  * Output an unsigned decimal longword.
  390.  */
  391. void
  392. PutUnsigned(
  393.         unsigned long        value
  394.     )
  395. {
  396.         if (value >= 10)
  397.             PutUnsigned(value / 10);
  398.         PutChar((value % 10) + '0');
  399. }
  400.  
  401. /*
  402.  * Output a string of hex digits with leading zeros.
  403.  */
  404. void
  405. PutHexLeadingZeros(
  406.         unsigned long        value,
  407.         short                digits
  408.     )
  409. {
  410.         if (--digits > 0)
  411.             PutHexLeadingZeros(value >> 4, digits);
  412.         value &= 0x0F;
  413.         PutChar((value < 10)
  414.                 ? value + '0'
  415.                 : (value + ('A' - 10))
  416.             );
  417. }
  418.  
  419. /*
  420.  * Output a 4-byte character string. Unknown
  421.  * bytes (characters outside the range ' ' to '~')
  422.  * are replaced as '.'.
  423.  */
  424. void
  425. PutOSType(
  426.         OSType                    datum
  427.     )
  428. {
  429.         char                    value[sizeof (OSType)];
  430.         register short            i;
  431.         register unsigned char    c;
  432.         
  433.         BlockMove(&datum, value, sizeof (OSType));
  434.         PutChar('\'');
  435.         for (i = 0; i < sizeof (OSType); i++) {
  436.             c = value[i];
  437.             if (c < ' ' || c >= 0x7F)
  438.                 c = '.';
  439.             PutChar(c);
  440.         }
  441.         PutChar('\'');
  442. }
  443.  
  444. void
  445. PutPascalString(
  446.         const StringPtr            datum
  447.     )
  448. {
  449.         dcmdDrawString(datum);
  450. }
  451.  
  452.  
  453. void
  454. PutChar(
  455.         unsigned char            datum
  456.     )
  457. {
  458.         char            work[1];
  459.         
  460.         if (datum == '\n')
  461.             PutLine();
  462.         else {
  463.             work[0] = datum;
  464.             dcmdDrawText((StringPtr) work, sizeof (char));
  465.         }
  466. }
  467.  
  468. void
  469. PutLine(void)
  470. {
  471.         dcmdDrawLine("\p");
  472. }
  473.